package com.sxj.PDMS.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sxj.PDMS.common.ErrorCode;
import com.sxj.PDMS.context.BaseContext;
import com.sxj.PDMS.exception.BusinessException;
import com.sxj.PDMS.mapper.AdminMapper;
import com.sxj.PDMS.model.dto.admin.AdminRegisterRequest;
import com.sxj.PDMS.model.entity.Admin;
import com.sxj.PDMS.model.entity.Student;
import com.sxj.PDMS.model.vo.AdminLoginVO;
import com.sxj.PDMS.service.AdminService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import javax.servlet.http.HttpServletRequest;

import static com.sxj.PDMS.utils.VerifyUtil.isValidChinesePhoneNumber;

/**
 * @author 503c'j
 * @description 针对表【admin(管理员)】的数据库操作Service实现
 * @createDate 2024-06-07 11:20:20
 */
@Service
@Slf4j
public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin>
        implements AdminService {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private AdminMapper adminMapper;
    public static final String SALT = "tyutrjxy";

    @Override
    public AdminLoginVO login(String adminId, String password, HttpServletRequest request) {
        // 1. 校验
        if (StringUtils.isAnyBlank(adminId, password)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        }
        if (adminId.length() < 4) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号错误");
        }
        if (password.length() < 6) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码错误");
        }
        // 2. 加密
        String encryptPassword = DigestUtils.md5DigestAsHex((SALT + password).getBytes());
        System.out.println("加密后的密码：" + encryptPassword);

        Object object = redisTemplate.opsForValue().get("admin:admin_" + adminId);
        if (object != null) {
            Admin admin = (Admin) object;
            if (!admin.getPassword().equals(encryptPassword)) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户不存在或密码错误");
            }
            AdminLoginVO adminLoginVO = new AdminLoginVO();
            BeanUtils.copyProperties(admin, adminLoginVO);
            return adminLoginVO;
        } else {
            //缓存中没有，从数据库中查询
            // 查询用户是否存在
            QueryWrapper<Admin> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("admin_id", adminId);
            queryWrapper.eq("password", encryptPassword);
            Admin admin = this.baseMapper.selectOne(queryWrapper);
            if (admin != null) {
                redisTemplate.opsForValue().set("admin:admin_" + adminId, admin, 7, TimeUnit.DAYS);
                AdminLoginVO adminLoginVO = new AdminLoginVO();
                BeanUtils.copyProperties(admin, adminLoginVO);
                return adminLoginVO;
            } else {
                log.info("user login failed, userAccount cannot match userPassword");
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户不存在或密码错误");
            }
        }


    }

    @Override
    public AdminLoginVO getLoginAdmin() {
        // 先判断是否已登录
        String currentId = BaseContext.getCurrentId();
        if (StringUtils.isBlank(currentId)) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }
        // todo 走redis缓存
        Object object = redisTemplate.opsForValue().get("admin:admin_" + currentId);
        if (object != null) {
            Admin admin = (Admin) object;
            AdminLoginVO adminLoginVO = new AdminLoginVO();
            BeanUtils.copyProperties(admin, adminLoginVO);
            return adminLoginVO;
        } else {
            // 从数据库查询（追求性能的话可以注释，直接走缓存）
            Admin currentUser = this.baseMapper.selectById(currentId);
            if (currentUser == null) {
                throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
            } else {
                redisTemplate.opsForValue().set("admin:admin_" + currentId, currentUser, 7, TimeUnit.DAYS);
                AdminLoginVO adminLoginVO = new AdminLoginVO();
                BeanUtils.copyProperties(currentUser, adminLoginVO);

                return adminLoginVO;
            }
        }
    }

    @Override
    public String register(AdminRegisterRequest adminRegisterRequest) {
        if (adminRegisterRequest.getAdminName() == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "名字为空");
        }
        if (adminRegisterRequest.getPassword().length() < 6 || adminRegisterRequest.getCheckPassword().length() < 6) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户密码过短");
        }
        // 密码和校验密码相同
        if (!adminRegisterRequest.getPassword().equals(adminRegisterRequest.getCheckPassword())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "两次输入的密码不一致");
        }
        if (!isValidChinesePhoneNumber(adminRegisterRequest.getPhoneNumber())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "手机号格式错误");
        }
        if (adminRegisterRequest.getAuth() == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "权限为空");
        }
        if (adminRegisterRequest.getAdminId() == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号为空");
        }

        synchronized (adminRegisterRequest.getAdminId().intern()) {
            // 账户不能重复
            QueryWrapper<Admin> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("admin_id", adminRegisterRequest.getAdminId());

            long count = adminMapper.selectCount(queryWrapper);

            if (count > 0) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, adminRegisterRequest.getAdminId() + "的账号已存在");
            }
            // 2. 加密
            // todo 修改加密方式
            String encryptPassword = DigestUtils.md5DigestAsHex((SALT + adminRegisterRequest.getPassword()).getBytes());
            // 3. 插入数据
            Admin admin = new Admin();

            BeanUtils.copyProperties(adminRegisterRequest, admin);
            admin.setPassword(encryptPassword);

            int inserted = adminMapper.insert(admin);
            if (inserted < 0) {
                throw new BusinessException(ErrorCode.SYSTEM_ERROR, "注册失败，数据库错误");
            }
        }
        return adminRegisterRequest.getAdminName();
    }
}




